package level;

import java.awt.Graphics;

import entity.lemming.Lemming;
import entity.lemming.Walker;
import entity.terrain.Terrain;



/************************************************************************************
 * 			POSSIBLY NOT FINAL DESIGN: LINKEDLIST IN PLACE OF ARRAYS				*
 * 																					*
 * May have allow for a lemmings backup ability as for climbing, floating ...		*
 ************************************************************************************/ 


/** 
 * A Lemming manager, responsible for resolving events invobylving 
 * Lemmings. Handles the morphing of Lemming types, collision, actions and 
 * the (alive) status of the Lemmings.
 * 
 * @author Neil Cowzer
 */
public class Manager{
	/** An array of Lemmings to be managed. */
	private Lemming[] lemmings;
	/*@ invariant
		lemmings != null
		&&
		(\forall int i; 0 <= i && i < lemmings.length;
		; lemmings[i].getParent() == this);
	@*/


	/** The current Level of the Lemming */
	private Level level;
	
	/** The current number of Lemmings alive */
	private int alive;
	/*@ invariant 0 <= alive &&
					   alive >= loaded;
	@*/
	
	/** The current status of the game */
	private boolean gameOver;
	//@ invariant (gameOver == true && alive == 0) || gameOver == false; 
	
	/** The current number of lemmings loaded. */
	private int loaded;
	/*@ invariant 0 <= loaded &&
	 				   loaded <= lemmings.length;
	@*/ 
	
	/**
	 * Create an instance of LemmingManager.
	 * 
	 * @param numOfLemmings the number of Lemmings in the level.
	 */
	/*@ requires numOfLemmings > 0 && level != null;
		assignable lemmings && level && alive && gameOver && loaded;
		ensures gameOver == false;
	@*/
	public Manager(int numOfLemmings, Level level){
		lemmings = new Lemming[numOfLemmings];
		this.level = level;
		this.alive = 0;
		
		// Ensure game is not over
		gameOver = false;
		loaded = 0;
	}
	
	/**
	 * Perform the logic of this game. Make each Lemming move once and 
	 * resolve any events accordingly.
	 */
	public void play(){
		Terrain[] terrain = level.getMap().getTerrain();
		if (alive < lemmings.length && loaded < lemmings.length){
			start();
		}
		
		for (int i = 0; i < lemmings.length; i++){
			if (lemmings[i] != null){
				if (lemmings[i].isAlive()){
					// Move lemming and handle any event accordingly
					for (int j = 0; j < terrain.length; j++){
						if (lemmings[i].collision(terrain[j])){
							lemmings[i].turnAround();
						}
					}
					
					lemmings[i].move();
					
					if (lemmings[i].energy() == 0)
						lemmings[i] = new Walker(lemmings[i].getX(),lemmings[i].getY());
					
					// Check for MousePositon
					mouseEvent(lemmings[i], 0, 0);
				
				}	
				// Allow for the width of the Lemming 
				if (lemmings[i].getX() < -10 || lemmings[i].getX() > 310 || lemmings[i].getY() < -10 || lemmings[i].getY() > 210){
					lemmings[i] = null;
					alive--;
				}

			}
		}
		
			// If there are no lemmings => GAMEOVER
			if (alive == 0)
				gameOver = true;
		}
	
	/**
	 * Create the new Lemmings as needed.
	 */
	/*@ ensures alive == \old(alive) + 1 &&
	 			loaded == \old(loaded) + 1;
	@*/
	public void start(){
		lemmings[alive] = new Walker(level.getMap().getStartX(), level.getMap().getStartY());
		alive++;
		loaded++;
	}
	
	/**
	 * Draw the Lemmings & Level to the Screen.
	 * 
	 * @param g
	 */
	public void draw(Graphics g){
		level.getMap().draw(g);
		for (int i = 0; i < lemmings.length; i++){
			if (lemmings[i] != null)
				lemmings[i].draw(g);
		}
		
	}
	
	/**
	 * Retrieve the array of Lemmings.
	 * 
	 * @return a an array of Lemmings.
	 */
	public /*@ pure @*/ Lemming[] getLemmings(){
		return lemmings;
	}
	
	// Possibly replace by a success or failure check!!!!!!
	/**
	 * Check to see if the game is over.
	 * 
	 * @return True if the game is over.
	 */
	public /*@ pure @*/ boolean gameOver(){
		return gameOver;
	}
	
	/**
	 * Handle the cursor positon and events accordingly.
	 * 
	 * @param y the X-coordinate of the cursor.
	 * @param x the Y-coordinate of the cursor.
	 * @param lemming a Lemming Object.
	 */
	//@	requires lemming != null && x >= 0 && y >= 0;
	private void mouseEvent(Lemming lemming, int x, int y){
		// only act if over a Lemming, otherwise ignore
		//for (int i = 0; i < lemmings.length; i++){
			if (lemming != null){
				// Is it over a lemming?
				if (lemming.getBounds().intersectsLine(x, y, x, y)){
					// Change to cursor....
					System.out.println("over a lemming");
				}
			}
		//}
	}
	
	/**
	 * Handles destruction/creation of terrain depending on type of lemming performing the action
	 *  
	 * @param lemming the type of lemming modifying the terrian
	 * @param x the x-coordinate of the terrain
	 * @param y	the y-coordinate of the terrain
	 */
	//@ requires lemming != null && x >= 0 && y >= 0;
	private void editTerrain(Lemming lemming, int x, int y){
		/*
		if (lemming.equals(Basher.class)){
			
		}
		else if (){
			
		}......
		*/
	}
}
